//
//  NetWorkTool.swift
//  GiteeClient
//
//  Created by 王志标 on 2020/10/15.
//

import UIKit
import Alamofire
import HandyJSON
import AwaitKit
import PromiseKit

/// 返回结果
struct Result<T> {
    var code:Int!
    var data:T?
    var message:String?
}

class NetWorkTool: NSObject {

    // 请求管理器 设置基本信息
    private var requsetManager:SessionManager?
    // 单例
    static var shared = NetWorkTool()
    
    private override init() {
        
        // 初始化请求管理器 配置相关参数
        let config = URLSessionConfiguration.default
        config.timeoutIntervalForRequest = 20.0
        requsetManager = SessionManager(configuration: config)
    }
    
}

// MARK: - get请求
extension NetWorkTool {
    
    // 请求项目
    func getRequestDefault<T:Any>(url:String!,method: HTTPMethod = .get, parmeters:[String: Any]? = nil,headers: HTTPHeaders? = nil)-> Result<T> {
        
        // 判断网络状况
       let rea = NetworkReachabilityManager(host: "https://www.baidu.com")
       if !(rea?.isReachable)!{
        return Result(code: -1, data: nil, message: "网络不可用")
       }
        
        var tokenUrl = url
        var tokenParmeters = parmeters
        // 区分 get 和pos
        if method == .get {
            
            if let token = UserDefaultTools.getToken() {
                if tokenUrl!.contains("?") {
                 
                    tokenUrl! += "&private_token=\(token)"
                }else {
                    tokenUrl! += "?private_token=\(token)"
                }
            }
            
        }else {
            if let token = UserDefaultTools.getToken() {
               
                if tokenParmeters == nil {
                    tokenParmeters = [:]
                }
                tokenParmeters!["private_token"] = token
            }
        }
        
        
        // 开始请求
        let promise = Alamofire.request(tokenUrl! , method: method, parameters: tokenParmeters, encoding: JSONEncoding.default, headers: headers).responseData()
        let res = try! await(promise)
        switch res.result {
                           
           case .success(let value):
            let str = String(data: value, encoding: .utf8)
            print("resultJson: = ",str ?? "")
            return Result(code: 0, data: str as? T, message: nil)//Result(code: 0, data: value.dateString(), message: nil)
            
           case .failure(let error):
               
               if error._code == NSURLErrorTimedOut {
                   return Result(code: -1, data: nil, message: "请求超时")
               }else {

                return Result(code: -1, data: nil, message: error.localizedDescription)
               }
           }
        
    }
    
    
    // 请求项目
    func getRequest<T: HandyJSON>(url:String!, method:HTTPMethod = .get,parameters: [String:Any]? = nil,headers: HTTPHeaders? = nil)-> Result<T> {
        
        // 判断网络状况
       let rea = NetworkReachabilityManager(host: "https://www.baidu.com")
       if !(rea?.isReachable)!{
        return Result(code: -1, data: nil, message: "网络不可用")
       }
        
        var tokenUrl = url
        var tokenParmeters = parameters
        // 区分 get 和pos
        if method == .get {
            
            if let token = UserDefaultTools.getToken() {
                if tokenUrl!.contains("?") {
                 
                    tokenUrl! += "&private_token=\(token)"
                }else {
                    tokenUrl! += "?private_token=\(token)"
                }
            }
            
        }else {
            if let token = UserDefaultTools.getToken() {
               
                if tokenParmeters == nil {
                    tokenParmeters = [:]
                }
                tokenParmeters!["private_token"] = token
            }
        }
       
        
        // 开始请求
        let promise = Alamofire.request(tokenUrl!, method: method, parameters: tokenParmeters, encoding: JSONEncoding.default, headers: headers).responseJSON()
        let res = try! await(promise)
        switch res.result {
                           
           case .success(let value):
               
            print("resultJson: = ",value)
            let data = value as? [String: Any]
               // 转化JsonParam模型 这个模型发送和服务器返回是同一个
            guard let model = T.deserialize(from: data) else
            {
                return Result(code: -1, data: nil, message: "数据解析失败")
                
            }
            
            return Result(code: 0, data: model, message: nil)
            
           case .failure(let error):
               
               if error._code == NSURLErrorTimedOut {
                   return Result(code: -1, data: nil, message: "请求超时")
               }else {

                return Result(code: -1, data: nil, message: error.localizedDescription)
               }
           }
        
    }
    
    // 请求项目列表的时候返回的是数组
    func getArrayRequest<T: HandyJSON>(url:String!,method: HTTPMethod = .get,parameters: [String:Any]?,headers:HTTPHeaders? = nil)-> Result<[T?]> {
        
        // 判断网络状况
       let rea = NetworkReachabilityManager(host: "https://www.baidu.com")
       if !(rea?.isReachable)!{
        return Result(code: -1, data: nil, message: "网络不可用")
       }
        
        var tokenUrl = url
        var tokenParmeters = parameters
        // 区分 get 和pos
        if method == .get {
            
            if let token = UserDefaultTools.getToken() {
                if tokenUrl!.contains("?") {
                 
                    tokenUrl! += "&private_token=\(token)"
                }else {
                    tokenUrl! += "?private_token=\(token)"
                }
            }
            
        }else {
            if let token = UserDefaultTools.getToken() {
               
                if tokenParmeters == nil {
                    tokenParmeters = [:]
                }
                tokenParmeters!["private_token"] = token
            }
        }
        
        // 开始请求
        let promise = Alamofire.request(tokenUrl!, method: .get, parameters: parameters, encoding: JSONEncoding.default, headers: headers).responseJSON()
        let res = try! await(promise)
        switch res.result {
                           
           case .success(let value):
               
            print("resultJson: = ",value)
            let data = value as? [[String: Any]]
               // 转化JsonParam模型 这个模型发送和服务器返回是同一个
            guard let model = [T].deserialize(from: data) else
            {
                return Result(code: -1, data: nil, message: "数据解析失败")
                
            }
            
            return Result(code: 0, data: model, message: nil)
            
           case .failure(let error):
               
               if error._code == NSURLErrorTimedOut {
                   return Result(code: -1, data: nil, message: "请求超时")
               }else {

                return Result(code: -1, data: nil, message: error.localizedDescription)
               }
           }
        
    }
}




extension Alamofire.DataRequest {
    public func response(queue: DispatchQueue? = nil) -> Promise<DefaultDataResponse> {
        let RequestQueue: DispatchQueue = DispatchQueue(label: "RequestQueue.Alamofire.DataRequest.response", attributes: .init(rawValue: 0))
        return Promise { seal in
            response(queue: RequestQueue) { response in
                seal.fulfill(response)
            }
        }
    }

    public func responseString() -> Promise<DataResponse<String>> {
        let RequestQueue: DispatchQueue = DispatchQueue(label: "RequestQueue.Alamofire.DataRequest.responseString", attributes: .init(rawValue: 0))
        return Promise { seal in
            responseString(queue: RequestQueue) { response in
                seal.fulfill(response)
            }
        }
    }

    public func responseData() -> Promise<DataResponse<Data>> {
        let RequestQueue: DispatchQueue = DispatchQueue(label: "RequestQueue.Alamofire.DataRequest.responseData", attributes: .init(rawValue: 0))
        return Promise { seal in
            responseData(queue: RequestQueue) { response in
                seal.fulfill(response)
            }
        }
    }

    public func responseJSON(options: JSONSerialization.ReadingOptions = .allowFragments) -> Promise<DataResponse<Any>> {
        let RequestQueue: DispatchQueue = DispatchQueue(label: "RequestQueue.Alamofire.DataRequest.responseJSON", attributes: .init(rawValue: 0))
        return Promise { seal in
            responseJSON(queue: RequestQueue, options: options) { response in
                seal.fulfill(response)
            }
        }
    }

    public func responsePropertyList(
            queue: DispatchQueue? = nil,
            options: PropertyListSerialization.ReadOptions = PropertyListSerialization.ReadOptions()
    ) -> Promise<DataResponse<Any>> {
        let RequestQueue: DispatchQueue = DispatchQueue(label: "RequestQueue.Alamofire.DataRequest.responsePropertyList", attributes: .init(rawValue: 0))
        return Promise { seal in
            responsePropertyList(queue: RequestQueue, options: options) { response in
                seal.fulfill(response)
            }
        }
    }
}

extension Alamofire.DownloadRequest {
    public func response(_: PMKNamespacer, queue: DispatchQueue? = nil) -> Promise<DefaultDownloadResponse> {
        let RequestQueue: DispatchQueue = DispatchQueue(label: "RequestQueue.Alamofire.DownloadRequest.response", attributes: .init(rawValue: 0))
        return Promise { seal in
            response(queue: RequestQueue) { response in
                seal.fulfill(response)
            }
        }
    }

    public func responseData(queue: DispatchQueue? = nil) -> Promise<DownloadResponse<Data>> {
        let RequestQueue: DispatchQueue = DispatchQueue(label: "RequestQueue.Alamofire.DownloadRequest.responseData", attributes: .init(rawValue: 0))
        return Promise { seal in
            responseData(queue: RequestQueue) { response in
                seal.fulfill(response)
            }
        }
    }
}
